<?php

namespace App\Service\OpenShop\Merchant;

use App\Enums\OpenShop\InvestmentPromotion\MainProcessEnum;
use App\Enums\OpenShop\InvestmentPromotion\SignOrderEnum;
use App\Enums\OpenShop\InvestmentPromotion\SiteMissionEnum;
use App\Enums\OpenShop\MissionTemplateEnum;
use App\Http\Resources\OpenShop\InvestmentPromotion\OrderDetailResource;
use App\Models\OpenShop\Common\OpenShopOrderManagerModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopMainProcessModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopProcessDetailModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSiteMissionModel;
use App\Models\OpenShop\Site\OpenShopMissionTemplateModel;
use App\Service\OpenShop\User\RmsUserService;
use App\Service\OpenShop\UserContractService;
use App\Service\OpenShop\Wap\SignOrderService;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Collection;

class OrderProgressService
{
    private OpenShopSignOrderModel         $signOrder;
    private OpenShopMainProcessModel       $mainProcess;
    private Collection                     $managerModels;
    private Collection                     $siteMissions;
    private Collection                     $template;
    private \Illuminate\Support\Collection $rmsUsers;
    private array                          $stepStatusLists;


    const PROGRESS_ORIGIN_APP    = 0;  //来源于商家APP
    const PROGRESS_ORIGIN_APPLET = 1;  //来源于开店飞书小程序

    /**
     * 准备数据
     * @param int $shopId
     * @return void
     * @throws GuzzleException
     */
    private function prepareData(): void
    {
        $this->mainProcess = OpenShopMainProcessModel::query()->where('orderNo', $this->signOrder->orderNo)->first();

        // 父子任务流程树
        $this->stepStatusLists = json_decode($this->mainProcess->stepStatusLists, true);
        $this->template        = OpenShopMissionTemplateModel::query()
                                                             ->whereIn('stepStatus', $this->stepStatusLists)
                                                             ->withoutGlobalScope('isDel')
                                                             ->select('name', 'mainStep', 'stepStatus')
                                                             ->get()
                                                             ->keyBy('stepStatus');

        // 任务列表 - 每个stepStatus都只取第一条任务
        $temStepStatus      = [];
        $this->siteMissions = OpenShopSiteMissionModel::query()
                                                      ->where('orderNo', $this->signOrder->orderNo)
                                                      ->orderBy('id')
                                                      ->get()
                                                      ->filter(function ($item) use (&$temStepStatus) {
                                                          if (!in_array($item->stepStatus, $temStepStatus)) {
                                                              $temStepStatus[] = $item->stepStatus;
                                                              return true;
                                                          }

                                                          return false;
                                                      })
                                                      ->keyBy('stepStatus');

        // 任务涉及到的经理人
        $this->managerModels = OpenShopOrderManagerModel::query()
                                                        ->where('mainProcessId', $this->mainProcess->id)
                                                        ->select('managerUid', 'managerName', 'type')
                                                        ->get()
                                                        ->keyBy('type');

        // 涉及到任务人的rms信息
        $rmsUids        = array_merge($this->siteMissions->pluck('dealUid')->toArray(),
            $this->managerModels->pluck('managerUid')->toArray());
        $this->rmsUsers = collect(RmsUserService::getRmsUserInfoByUserIds($rmsUids)['data'])->keyBy('id');
    }

    public function setOrderNo(string $orderNo): self
    {
        $this->signOrder = (new SignOrderService($orderNo, null))->getSignOrderInMerchant();

        return $this;
    }

    public function setShopId(int $shopId): self
    {
        $this->signOrder = (new SignOrderService('',
            OpenShopSignOrderModel::getModelByShopId($shopId)))->getSignOrderInMerchant();

        return $this;
    }

    /**
     * 主流程调用方法
     * @param int $shopId
     * @return array
     * @throws GuzzleException
     */
    public function progress(int $origin = OrderProgressService::PROGRESS_ORIGIN_APP): array
    {
        // 准备数据
        $this->prepareData();

        // 流程架
        $mainStepLists = [];
        foreach ($this->stepStatusLists as $stepStatus) {
            $mainStep                   = $this->template[$stepStatus]['mainStep'] ?? 0;
            $mainStepLists[$mainStep][] = $stepStatus;
        }

        $mainStepEmpty = false;
        $nowMainStep   = MainProcessEnum::MAIN_PROCESS_INVESTMENT_SIGN;
        $progressLists = [];
        foreach ($mainStepLists as $mainStep => $stepLists) {

            // 父级主流程全空
            if ($mainStepEmpty) {
                $progressLists[$mainStep]['lists'] = [];
                $progressLists[$mainStep]          = [
                    'lists'   => [],
                    'text'    => MainProcessEnum::MAIN_PROCESS_MAP[$mainStep] ?? '',
                    'total'   => 0,
                    'current' => 0,
                    'status'  => '未开始',
                    'nextNum' => 0,
                ];
                continue;
            }

            // 通过自流程的最后一个任务是否有完成时间判断当前流程是否已经完成
            $judgmentProgressFinish = function ($list) {
                $data = end($list)['date'] ?? '';
                if (strlen($data)) {
                    return '已完成';
                } else {
                    return '未完成';
                }
            };

            // 子流程处理
            $progressLists[$mainStep] = [
                'lists'   => $lists = $this->progressLists($mainStep, $stepLists, $origin),
                'text'    => MainProcessEnum::MAIN_PROCESS_MAP[$mainStep] ?? '',
                'total'   => $total = count($stepLists),
                'current' => $current = collect($lists)->where('status', 1)->count(),
                // 'status'  => $sta = ($total == $current ? '已完成' : '待完成'),  下面调整为取最后一个流程的状态
                'status'  => $sta = $judgmentProgressFinish($lists),
                'nextNum' => ($sta == '待完成') ? ($total - $current - 1) : 0,
            ];

            if ($sta == '待完成') {
                $mainStepEmpty = !$origin;
                $nowMainStep   = $mainStep;
            }
        }

        // 一直没有待完成，那就是跑完流程了
        if (!$mainStepEmpty) {
            $nowMainStep = MainProcessEnum::MAIN_PROCESS_START_BUSINESS;
        }

        if ($origin == OrderProgressService::PROGRESS_ORIGIN_APPLET) {
            foreach ($progressLists as $k => $progressList) {
                if ($progressList['current'] == 0) {
                    $progressLists[$k]['status'] = '未开始';
                }
            }
        }

        return [
            'manager'  => $this->manager($nowMainStep),
            'progress' => array_values($progressLists),
            'jumpUrl'  => $this->getJumpUrl(), // 强制跳转url
        ];
    }

    /**
     * 强制跳转链接
     * @return string
     * @throws \Exception
     */
    private function getJumpUrl(): string
    {
        $jumpUrl = '';

        // 强制跳转
        if ($this->mainProcess->nowStepStatus >= MissionTemplateEnum::STEP_STATUS_5) {

            list($isFinalPay, $lastPrice, $depositAmount) = UserContractService::getLastPrice($this->signOrder);

            if ($depositAmount > 0 && $isFinalPay && $lastPrice > 0) {
                $jumpUrl = 'kuafoodmerchantapp://webView?url=';
                $jumpUrl .= OrderDetailResource::formatSignUrl($this->signOrder->orderNo);
            }
        }

        return $jumpUrl;
    }

    // 子流程处理
    private function progressLists(
        int $mainStep,
        array $stepLists,
        int $origin = OrderProgressService::PROGRESS_ORIGIN_APP
    ): array {
        $progressMainStepList = [];

        // 前3步的操作日志
        if ($mainStep == MainProcessEnum::MAIN_PROCESS_INVESTMENT_SIGN) {
            $processDetails = OpenShopProcessDetailModel::query()
                                                        ->where('mainProcessId', $this->mainProcess->id)
                                                        ->where('mainProcessType',
                                                            MainProcessEnum::MAIN_PROCESS_INVESTMENT_SIGN)
                                                        ->where('status', 1)
                                                        ->get()
                                                        ->keyBy('processType');
        }

        foreach ($stepLists as $stepStatus) {

            // 商家签约阶段 - 不走任务表，需要单独处理
            if ($mainStep == MainProcessEnum::MAIN_PROCESS_INVESTMENT_SIGN) {
                $processDetail = $processDetails[$stepStatus + 1] ?? [];

                if ($stepStatus == MissionTemplateEnum::STEP_STATUS_0 && $this->mainProcess->childOrder == MainProcessEnum::CHILD_ORDER_0) {
                    $progressMainStepList[] = [
                        'desc'       => '订单号：' . $this->signOrder->orderNo,
                        'text'       => $this->template[$stepStatus]['name'] ?? '',
                        'handlerUid' => $processDetail['createdByUid'] ?? 0,
                        'handler'    => '处理人:' . $this->signOrder->investmentManagerName,
                        'status'     => 1, // 0没做 1做了
                        'date'       => $processDetail ? $processDetail->createdAt->format('m-d H:i') : '-',
                    ];
                } elseif ($stepStatus == MissionTemplateEnum::STEP_STATUS_1 && $this->mainProcess->childOrder == MainProcessEnum::CHILD_ORDER_0) {
                    $progressMainStepList[] = [
                        'desc'       => '支付金额：￥' . bcdiv($this->signOrder->payPrice, 100, 2),
                        'text'       => $this->template[$stepStatus]['name'] ?? '',
                        'handlerUid' => $this->signOrder->merchantUserId,
                        'handler'    => '处理人:' . ((string)optional($this->signOrder->identityCardRel)->name),
                        'status'     => (int)($this->signOrder->step >= SignOrderEnum::STEP_4), // 0没做 1做了
                        'date'       => $processDetail ? $processDetail->createdAt->format('m-d H:i') : '-',
                    ];
                } elseif ($stepStatus == MissionTemplateEnum::STEP_STATUS_2) {
                    $progressMainStepList[] = [
                        'desc'       => '合同编号：KF-' . $this->signOrder->shopCode,
                        'text'       => $this->template[$stepStatus]['name'] ?? '',
                        'handlerUid' => $this->signOrder->merchantUserId,
                        'handler'    => '处理人:' . ((string)optional($this->signOrder->identityCardRel)->name),
                        'status'     => $status = (int)(bool)($this->signOrder->signTime), // 0没做 1做了
                        'date'       => $status && $processDetail ? $processDetail->createdAt->format('m-d H:i') : '',
                    ];
                }

                continue;
            }

            // mainStep > 1的阶段
            if (!isset($this->siteMissions[$stepStatus])) {
                if ($origin) {
                    $progressMainStepList[] = [
                        'desc'       => '',
                        'text'       => $this->template[$stepStatus]['name'] ?? '',
                        'handlerUid' => 0,
                        'handler'    => '',
                        'status'     => 0, // 0没做 1做了
                        'date'       => '',
                    ];
                }
                continue;
            }

            $siteMission = $this->siteMissions[$stepStatus];
            $status      = (int)($this->siteMissions[$stepStatus]['status'] == SiteMissionEnum::STATUS_2);
            $completeAt  = $this->siteMissions[$stepStatus]['completeAt'] ?? 0;
            $desc        = $this->getDesc($stepStatus);

            $progressMainStepList[] = [
                'desc'       => $desc,
                'text'       => $this->template[$stepStatus]['name'] ?? '',
                'handlerUid' => $dealUid = $siteMission['dealUid'] ?? 0,
                'handler'    => '处理人:' . ($this->rmsUsers[$dealUid]['username'] ?? ''),
                'status'     => $status, // 0没做 1做了
                'date'       => $completeAt ? date('m-d H:i', $completeAt) : '',
            ];
        }

        return $progressMainStepList;
    }

    /**
     * @param int $stepStatus
     * @return string
     */
    private function getDesc(int $stepStatus): string
    {
        switch ($stepStatus) {
            case MissionTemplateEnum::STEP_STATUS_3:
                $managerType = OpenShopOrderManagerModel::MANAGER_TYPE_2;
                break;
            case MissionTemplateEnum::STEP_STATUS_6:
                $managerType = OpenShopOrderManagerModel::MANAGER_TYPE_4;
                break;
            case MissionTemplateEnum::STEP_STATUS_7:
                $managerType = OpenShopOrderManagerModel::MANAGER_TYPE_3;
                break;
            case MissionTemplateEnum::STEP_STATUS_11:
                $managerType = OpenShopOrderManagerModel::MANAGER_TYPE_5;
                break;
            default:
                $managerType = 0;
        }

        if ($managerType) {
            $manager = $this->managerModels[$managerType] ?? [];
            $desc    = (OpenShopOrderManagerModel::TYPE_MAP[$managerType] ?? '') . ':' . ($manager['managerName'] ?? '');
        } else {
            $desc = '';
        }

        return $desc;
    }

    /**
     * 顶部展示的客服，对应顾问信息
     * @param int $nowMainStep
     * @return array
     */
    private function manager(int $nowMainStep): array
    {
        if ($nowMainStep == MainProcessEnum::MAIN_PROCESS_INVESTMENT_SIGN) {
            $res = [
                'uid'      => $uid = (int)$this->signOrder->investmentManagerId,
                'username' => (string)$this->signOrder->investmentManagerName,
                'type'     => OpenShopOrderManagerModel::TYPE_MAP[OpenShopOrderManagerModel::MANAGER_TYPE_1] ?? '',
                'mobile'   => $this->rmsUsers[$uid]['mobile'] ?? '',
            ];
        } elseif ($nowMainStep == MainProcessEnum::MAIN_PROCESS_SHOP_LOCATION) {
            $manager = $this->managerModels[OpenShopOrderManagerModel::MANAGER_TYPE_2] ?? [];

            $res = [
                'uid'      => $uid = $manager['managerUid'] ?? 0,
                'username' => $manager['managerName'] ?? '',
                'type'     => OpenShopOrderManagerModel::TYPE_MAP[OpenShopOrderManagerModel::MANAGER_TYPE_2] ?? '',
                'mobile'   => $this->rmsUsers[$uid]['mobile'] ?? '',
            ];
        } elseif ($nowMainStep == MainProcessEnum::MAIN_PROCESS_START_BUSINESS) {
            $manager = $this->managerModels[OpenShopOrderManagerModel::MANAGER_TYPE_5] ?? [];
            $res     = [
                'uid'      => $uid = $manager['managerUid'] ?? 0,
                'username' => $manager['managerName'] ?? '',
                'type'     => OpenShopOrderManagerModel::TYPE_MAP[OpenShopOrderManagerModel::MANAGER_TYPE_5] ?? '',
                'mobile'   => $this->rmsUsers[$uid]['mobile'] ?? '',
            ];
        } else {
            $manager = $this->managerModels[OpenShopOrderManagerModel::MANAGER_TYPE_4] ?? [];

            $res = [
                'uid'      => $uid = $manager['managerUid'] ?? 0,
                'username' => $manager['managerName'] ?? '',
                'type'     => OpenShopOrderManagerModel::TYPE_MAP[OpenShopOrderManagerModel::MANAGER_TYPE_4] ?? '',
                'mobile'   => $this->rmsUsers[$uid]['mobile'] ?? '',
            ];
        }

        // 解决开发经理可能为空的问题
        if ($res['uid'] == 0 && $nowMainStep == MainProcessEnum::MAIN_PROCESS_SHOP_LOCATION) {
            return $this->manager(MainProcessEnum::MAIN_PROCESS_INVESTMENT_SIGN);
        }

        return $res;
    }
}
